package omm.domain.generalgraph;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import org.joda.time.DateTime;

import omm.domain.Graphic;
import omm.domain.Quotation;
import omm.domain.Quotation.State;
import omm.util.Graphics;

/**
 * Se encarga de la creacion del grafico de cantidad
 */

public class QuantityGraphic implements Graphic {
	private String urlformat = "http://chart.apis.google.com/chart?chs=430x200"
			+ "&amp;chd=t:%d,%d,%d&amp;cht=p"
			+ "&amp;chl=Pendiente(%d%%)|Ganada(%d%%)|Perdida(%d%%)&amp;chco=8b0027&amp;chtt=%s&amp;chts=000000,20"
			+ "&amp;chxs=0,000000,18&amp;chxt=x";

	private final List<Quotation> quotations;
	private final DateTime beginning;
	private final DateTime ending;
	private final Map<Quotation.State, Integer> commisionQuantityMap;

	public QuantityGraphic(List<Quotation> quotations, DateTime beginning, DateTime ending) {
		this.quotations = quotations;
		this.beginning = beginning;
		this.ending = ending;
		this.commisionQuantityMap = calculateCommisionQuantityMap();
	}

	public String getGraphicURL() {
		Map<Quotation.State, Integer> map = calculateGraphicAttributes();

		int quoted = 0;
		int won = 0;
		int lost = 0;
		String title = Graphics.makeTitle("CANTIDAD DE EMPRESAS", this.beginning, this.ending);
		if (map != null) {
			quoted = map.get(State.QUOTED);
			won = map.get(State.WON);
			lost = map.get(State.LOST);
		}

		Object[] params = { quoted, won, lost, quoted, won, lost, title };
		return String.format(urlformat, params);
	}

	public Map<State, Integer> getCommisionDataMap() {
		return commisionQuantityMap;
	}

	private Map<Quotation.State, Integer> calculateCommisionQuantityMap() {
		Map<Quotation.State, Integer> map = initCommisionSumMap();
				
		Map<Integer,Quotation.State> entitiesStates = calculateEntitiesStates();
		for (Entry<Integer, State> e : entitiesStates.entrySet()) {
			System.out.println("EMPRESA: "+e.getKey()+" ESTADO: "+e.getValue());
			Integer actualQuantity = map.get(e.getValue());
			map.put(e.getValue(), (actualQuantity != null) ? (actualQuantity + 1) : 1);
		}
		return map;
	}
	//TODO: Esto se repite un poco en ClientsQuantityUnitStrategy. Centralizarlo
	/***
	 * Calcula para cada entidad el estado que tiene segun sus cotizaciones
	 * @return map ordenado por id de empresa con sus estados correspondientes
	 */
	private Map<Integer, State> calculateEntitiesStates() {
		Map<Integer, State> entitiesStates = new LinkedHashMap<Integer, State>();
		Iterator<Quotation> it = quotations.iterator();
		while (it.hasNext()) {
			Quotation q = it.next();
			try{
				Integer clientID = q.getOrder().getId();
				//Devuelve null si no se encuentra en el map
				State currentState = entitiesStates.get(clientID);
				//Si ya tenia estado de WON no me fijo porque ya esta ganada
				if(currentState != State.WON){
					if(((currentState == null)||
						((currentState == State.LOST)||(currentState == State.QUOTED))&&(q.getState() == State.WON))||
						((currentState == State.QUOTED)&&((q.getState() == State.WON)||(q.getState() == State.LOST)))){
							entitiesStates.put(clientID, q.getState());
						}
				}
			}catch(Exception e){
				//TODO:Loggear
			}
		}
		return entitiesStates;
	}

	private Map<State, Integer> calculateGraphicAttributes() {

		Integer total = commisionQuantityMap.get(State.QUOTED) 
				+ commisionQuantityMap.get(State.WON)
				+ commisionQuantityMap.get(State.LOST);
		if (total == 0)
			return null;

		// calculo de los porcentajes
		Integer quotedPercent = (int) (Math.round(((double) commisionQuantityMap.get(State.QUOTED) * 100) / total));
		Integer wonPercent = (int) (Math.round(((double) commisionQuantityMap.get(State.WON) * 100) / total));
		Integer lostPercent = (int) (Math.round(((double) commisionQuantityMap.get(State.LOST) * 100) / total));

		// Del perl! Redondeo
		int porc_total_entero = 0;
		porc_total_entero += quotedPercent + wonPercent + lostPercent;

		Map<Quotation.State, Integer> percentajesMap = initPercentagesMap();
		percentajesMap.put(State.QUOTED, quotedPercent);
		percentajesMap.put(State.WON, wonPercent);
		percentajesMap.put(State.LOST, lostPercent);

		int dif = 0;
		State state = null;
		int max_portion = 0;
		if (porc_total_entero != 100) {
			for (Quotation.State s : Quotation.State.values()) {
				if ((s == State.LOST) || (s == State.WON) || (s == State.QUOTED))
					if (percentajesMap.get(s) >= max_portion) {
						max_portion = percentajesMap.get(s);
						state = s;
					}
			}
			dif = porc_total_entero - 100;
			if (dif == 2 || dif == -2) {
				State state2 = null;
				dif /= 2;
				for (Quotation.State s : Quotation.State.values()) {
					if (((s == State.LOST) || (s == State.WON) || (s == State.QUOTED)) && (s != state2))
						if (percentajesMap.get(s) >= max_portion) {
							max_portion = percentajesMap.get(s);
							state2 = s;
						}
				}
				percentajesMap.put(state2, percentajesMap.get(state2) - dif);
			}
			percentajesMap.put(state, percentajesMap.get(state) - dif);
		}

		return percentajesMap;

	}

	private Map<State, Integer> initPercentagesMap() {
		Map<State, Integer> percentajesMap = new HashMap<Quotation.State, Integer>();
		for (Quotation.State s : Quotation.State.values()) {
			percentajesMap.put(s, 0);
		}
		return percentajesMap;
	}

	private Map<State, Integer> initCommisionSumMap() {
		Map<Quotation.State, Integer> commisionQuantityMap = new HashMap<Quotation.State, Integer>();
		for (Quotation.State s : Quotation.State.values()) {
			commisionQuantityMap.put(s, 0);
		}

		return commisionQuantityMap;
	}

}
